package com.googlecode.jch.plugin.runconfiguration;

import com.googlecode.jch.plugin.JCHUtil;
import com.intellij.execution.ui.AlternativeJREPanel;
import com.intellij.execution.ui.ClassBrowser;
import com.intellij.execution.ui.CommonJavaParametersPanel;
import com.intellij.execution.ui.ConfigurationModuleSelector;
import com.intellij.ide.util.ClassFilter;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Iskander Akishev
 */
public class JCHRunConfigurable extends SettingsEditor<JCHRunConfiguration> {
	private JPanel myWholePanel;
	private LabeledComponent<TextFieldWithBrowseButton.NoPathCompletion> mySolutionClass;
	private CommonJavaParametersPanel myCommonProgramParameters;
	private final ConfigurationModuleSelector myModuleSelector;
	private LabeledComponent<JComboBox> myModule;
	private AlternativeJREPanel myAlternativeJREPanel;

	public JCHRunConfigurable(Project project) {
		myModuleSelector = new ConfigurationModuleSelector(project, myModule.getComponent());
		myModule.getComponent().addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				myCommonProgramParameters.setModuleContext(myModuleSelector.getModule());
			}
		});
		new SolutionClassBrowser(project, myModuleSelector).setField(getSolutionClassField());
		myCommonProgramParameters.getProgramParametersComponent().setVisible(false);
	}

	@Override
	protected void resetEditorFrom(JCHRunConfiguration configuration) {
		myCommonProgramParameters.reset(configuration);
		myModuleSelector.reset(configuration);
		getSolutionClassField().setText(configuration.SOLUTION_CLASS_NAME);
		myAlternativeJREPanel.init(configuration.ALTERNATIVE_JRE_PATH, configuration.ALTERNATIVE_JRE_PATH_ENABLED);
	}

	@Override
	protected void applyEditorTo(JCHRunConfiguration configuration) throws ConfigurationException {
		myCommonProgramParameters.applyTo(configuration);
		myModuleSelector.applyTo(configuration);
		configuration.SOLUTION_CLASS_NAME = getSolutionClassField().getText();
		configuration.ALTERNATIVE_JRE_PATH = myAlternativeJREPanel.getPath();
		configuration.ALTERNATIVE_JRE_PATH_ENABLED = myAlternativeJREPanel.isPathEnabled();
	}

	@NotNull
	@Override
	protected JComponent createEditor() {
		return myWholePanel;
	}

	@Override
	protected void disposeEditor() {
	}

	private TextFieldWithBrowseButton getSolutionClassField() {
		return mySolutionClass.getComponent();
	}

	private static class SolutionClassBrowser extends ClassBrowser {
		private final Project myProject;
		private final ConfigurationModuleSelector myModuleSelector;

		private static final ClassFilter classFilter = new ClassFilter() {
			public boolean isAccepted(PsiClass psiClass) {
				return JCHUtil.isSolutionClass(psiClass);
			}
		};

		public SolutionClassBrowser(final Project project, final ConfigurationModuleSelector moduleSelector) {
			super(project, "Choose Solution Class");
			myProject = project;
			myModuleSelector = moduleSelector;
		}

		@Override
		protected ClassFilter.ClassFilterWithScope getFilter() throws NoFilterException {
			final Module module = myModuleSelector.getModule();
			final GlobalSearchScope scope = module == null ?
				GlobalSearchScope.allScope(myProject) :
				GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module);
			return new ClassFilter.ClassFilterWithScope() {
				public GlobalSearchScope getScope() {
					return scope;
				}

				public boolean isAccepted(final PsiClass aClass) {
					return classFilter == null || classFilter.isAccepted(aClass);
				}
			};
		}

		@Override
		protected PsiClass findClass(String className) {
			return myModuleSelector.findClass(className);
		}
	}
}
